/*
 * vim:ts=3:sw=3:sts=3:expandtab
 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <Ecore.h>
#include <Ecore_Evas.h>
#include <Edje.h>
#include <Evas.h>

#include <assert.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "image_container_smart.h"

static void _delete_request_cb(Ecore_Evas *ee);
static void _resize_cb(Ecore_Evas *ee);
static void _mouse_down_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info);
static void _mouse_up_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info);
static void _mouse_move_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info);

#define MAX(x, y) ((x) > (y) ? (x) : (y))
#define MIN(x, y) ((x) < (y) ? (x) : (y))

/* exported var */
static Evas_Object *obj;
static int _mouse_down = 0;
static int _mouse_down_x = 0;
static int _mouse_down_y = 0;

static void usage(void)
{
   fprintf(stderr, "usage: image_container [--engine=ENGINE] [--geometry=GEOMETRY] [--fullscreen] [--verbose] [--help]\n");
   fprintf(stderr, "\n"
                   "   --engine      Which display engine to use (x11, x11-16). Default=x11\n"
                   "   --geometry    Window geometry (<width>x<height>)\n"
                   "   --fullscreen  Launch in fullscreen mode\n"
                   "   --verbose     Turn on verbose mode\n"
                   "   --help        Display this help and exit\n");
}

int main(int argc, char **argv)
{
   Ecore_Evas *ee;
   Evas *evas;
   Ecore_Evas_Engine_Type engine_type = ECORE_EVAS_ENGINE_SOFTWARE_X11;
   int w = 800, h = 480;
   int fullscreen = 0;
   int verbose = 0;
   int i;
   int option;
   struct option long_opts[] = {
      { "engine",     1, NULL, 'e' },
      { "geometry",   1, NULL, 'g' },
      { "fullscreen", 0, NULL, 'f' },
      { "verbose",    0, NULL, 'v' },
      { "help",       0, NULL, 'h' },
      { NULL,         0, NULL, 0 }
   };

   /* make sure ecore evas engine software x11 is supported */
   assert(ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_SOFTWARE_X11));

   /* parse options */
   while ((option = getopt_long(argc, argv, "e:g:fvh", long_opts, NULL)) != -1)
   {
      switch (option)
      {
         case 'e':
            if (strcmp(optarg, "x11-16") == 0)
            {
               if (ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_SOFTWARE_X11_16))
                  engine_type = ECORE_EVAS_ENGINE_SOFTWARE_X11_16;
               else
                  fprintf(stderr, "engine x11-16 is not available, falling back to x11\n");
            }
            else if (strcmp(optarg, "x11") != 0)
               fprintf(stderr, "invalid engine %s, falling back to x11\n", optarg);
            break;
         case 'g':
            {
               char *p;

               p = strchr(optarg, 'x');
               if (p)
               {
                  w = atoi(optarg);
                  h = atoi(p + 1);
               }
               else
                  fprintf(stderr, "invalid geometry format, using 800x600\n");
            }
            break;
         case 'f':
            fullscreen = 1;
            break;
         case 'v':
            verbose = 1;
            break;
         case 'h':
            usage();
            return 0;
         default:
            break;
      }
   }

   fprintf(stderr, "engine:%d geometry:%dx%d fullscreen:%d verbose:%d\n",
           engine_type, w, h, fullscreen, verbose);

   /* initialize all subsystems */
   evas_init();
   ecore_init();
   ecore_app_args_set(argc, (const char **)argv);
   ecore_evas_init();
   edje_init();

   if (engine_type == ECORE_EVAS_ENGINE_SOFTWARE_X11)
   {
      fprintf(stderr, "creating ecore evas software X11\n");
      ee = ecore_evas_software_x11_new(NULL, 0, 0, 0, w, h);
   }
   else
   {
      fprintf(stderr, "creating ecore evas software X11 16\n");
      ee = ecore_evas_software_x11_16_new(NULL, 0, 0, 0, w, h);
   }
   ecore_evas_callback_delete_request_set(ee, _delete_request_cb);
   ecore_evas_title_set(ee, "Image Preview");
   ecore_evas_name_class_set(ee, "image_container", "main");
   ecore_evas_fullscreen_set(ee, fullscreen);
   ecore_evas_show(ee);

   evas = ecore_evas_get(ee);
   evas_image_cache_set(evas, 8 * 1024 * 1024);

   obj = image_container_object_add(evas);
   // image_container_object_preview_mode_set(obj, 1);
   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, NULL);
   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, NULL);
   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb, NULL);
   evas_object_move(obj, 0, 0);
   evas_object_resize(obj, w, h);
   evas_object_show(obj);
   for (i = optind; i < argc; ++i)
      image_container_object_append(obj, argv[i], NULL);

   ecore_evas_callback_resize_set(ee, _resize_cb);

   ecore_main_loop_begin();

   return 0;
}

static void
_delete_request_cb(Ecore_Evas *ee)
{
   ecore_main_loop_quit();
}

static void
_resize_cb(Ecore_Evas *ee)
{
   Evas *evas;
   Evas_Coord w, h;

   evas = ecore_evas_get(ee);
   evas_output_viewport_get(evas, NULL, NULL, &w, &h);
   evas_object_resize(obj, w, h);
}

static void
_mouse_down_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info)
{
   Evas_Event_Mouse_Down *e = event_info;

   _mouse_down = 1;
   _mouse_down_x = e->output.x;
   _mouse_down_y = e->output.y;
}

static void
_mouse_up_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info)
{
   _mouse_down = 0;
}

static void
_mouse_move_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info)
{
   Evas_Event_Mouse_Move *e = event_info;
   int scroll_offset;

   if (!_mouse_down)
      return;

   scroll_offset = image_container_object_scroll_offset_get(obj);
   scroll_offset += (e->cur.output.x - _mouse_down_x);
   if (scroll_offset > 0)
      scroll_offset = 0;
   else
     {
	int ow, iw;

	evas_object_geometry_get(obj, NULL, NULL, &ow, NULL);
	image_container_object_items_bounds_get(obj, NULL, NULL, &iw, NULL);
	if (scroll_offset < -(iw - ow))
	   scroll_offset = -(iw - ow);
     }
   image_container_object_scroll_offset_set(obj, scroll_offset);
   _mouse_down_x = e->cur.output.x;
}
